﻿using System;
using System.Collections.Generic;

using System.Reflection;
using System.Text;
using EnvDTE;
using EnvDTE80;

namespace TddGenerator.Core.Services.Impl
{
    public class VsIdeService:IVsIdeService
    {
        private readonly DTE2 dte;
        private readonly IFileSystemService fileSystemService;

        public VsIdeService(DTE2 det, IFileSystemService fileSystemService)
        {
            this.dte = det;
            this.fileSystemService = fileSystemService;
        }

        public string SolutionFoldername()
        {
            return fileSystemService.GetDirectoryName(dte.Solution.FileName);
        }

        public string GetRootNamespace(string ProjectName)
        {
            return GetNamespace(ProjectName);
        }

        public void CreateFolderHierarchy(string projectName, IEnumerable<string> folderHierarchy)
        {
            GetFolderItems(projectName, folderHierarchy);
        }

        private ProjectItems GetFolderItems(string projectName, IEnumerable<string> folderHierarchy)
        {
            Project ClassProject = GetProjectInstance(projectName);

            ProjectItems items = ClassProject.ProjectItems;
            foreach (string foldername in folderHierarchy)
            {
                ProjectItem folder = GetFolder(foldername, items);
                items = folder.ProjectItems;
            }
            return items;
        }

        private ProjectItem GetFolder(string folderName, ProjectItems ProjectItems)
        {
            ProjectItem folder = null;
            foreach (ProjectItem item in ProjectItems)
            {
                if (item.Name == folderName)
                {
                    folder = item;
                    break;
                }
            }
            if (folder == null)
            {
                folder = AddOrCreateFolder(ProjectItems, folderName);
            }
            return folder;
        }

        private ProjectItem AddOrCreateFolder(ProjectItems ProjectItems, string folderName)
        {
            ProjectItem folder;
            string folderDirectoryName = fileSystemService.GetDirectoryName(ProjectItems.ContainingProject.FileName) + "\\" + folderName;
            if (fileSystemService.FolderExists(folderDirectoryName))
            {
                folder = ProjectItems.AddFromDirectory(folderDirectoryName);
            }
            else
                folder = ProjectItems.AddFolder(folderName, Constants.vsProjectItemKindPhysicalFolder);
            return folder;
        }

        public void AddFileToFolder(string projectName, IEnumerable<string> folderHierarchy, string fileName,
                                    string templateFilePath)
        {
            ProjectItems items = GetFolderItems(projectName, folderHierarchy);
            ProjectItem cutitem = items.AddFromFileCopy(templateFilePath);
            cutitem.Name = fileName;
        }

        public void ReplaceTokens(string project, IList<string> folderHierarchy, string filename,
                                  IDictionary<string, string> tokens)
        {
            ProjectItems items = GetFolderItems(project, folderHierarchy);
            ProjectItem cutitem = items.Item(filename);
            cutitem.Open(Constants.vsViewKindCode);
            foreach(KeyValuePair<string,string> keyvaluepair in tokens)
            {
                cutitem.Document.ReplaceText(keyvaluepair.Key, keyvaluepair.Value, 0);
            }
            cutitem.Save(cutitem.get_FileNames(0));
            cutitem.Document.Activate();
        }

        private string GetNamespace(string project)
        {
            Project ClassProject = GetProjectInstance(project);

            return GetDefaultNamespace(ClassProject);
        }

        private string GetDefaultNamespace(Project ClassProject)
        {
            string DefaultNamespace = ClassProject.Properties.Item("RootNamespace").Value.ToString();
            return DefaultNamespace;
        }

        private Project GetProjectInstance(string projectName)
        {            
            foreach (Project item in dte.Solution.Projects)
            {
                if (item.Name == projectName)
                {
                    return item;
                }
            }
            return null;
        }
    }
}
